/**
 * MCU 系统滴答时钟适配 API 头文件
 * Copyright (c) 2021 深圳市智辰科技有限公司
 * All rights reserved.
 */

#ifndef _SYS_CLOCK_H_
#define _SYS_CLOCK_H_

#include "stdc.h"

#ifdef __cplusplus
extern "C" {
#endif


/// @brief 时间精度(osGetUs()/osElapsedUs()/osGetMs()/osElapsedMs())
typedef uint32_t timeu_t;

/// @brief 获取当前系统时钟微秒数
//#define osGetUs() 		((timeu_t)(esp_clk_rtc_time() & 0xFFFFFFFF))
#define osGetUs()			((timeu_t)(esp_timer_get_time() & 0xFFFFFFFF))
/// @brief 计算已经逝去的时间微秒数
#define osElapsedUs(last)	(osGetUs() - last)
/// @brief 延时us
//#define osDelayUs(x)    	usleep(x) // in <unistd.h>
#define osDelayUs(x)    	ets_delay_us(x)

/// @brief 获取当前系统时钟毫秒数
//#define osGetMs()			((timeu_t)((esp_clk_rtc_time()/1000) & 0xFFFFFFFF))
#define osGetMs()			((timeu_t)(esp_timer_get_time() / 1000))
/// @brief 计算已经逝去的时间毫秒数
#define osElapsedMs(last)	(osGetMs() - last)
/// @brief 延时ms
#define osDelayMs(x)   		vTaskDelay((x) / portTICK_PERIOD_MS)

/// @brief 获得当前时间(自1970-1-1 00:00:00至当前的秒数)
long osGetTime();
#define osGetS()			osGetTime()
/// @brief 获得当前时间(当天的秒数)
#define osGetClock() 		((uint32_t)(osGetTime() % (24*60*60)))
/// @brief 获得当前时区的时间
struct tm osGetLocalDateTime();
/// @brief 获得当前时区的时间字符串
/// 注意: 本函数使用了静态字符串缓冲区，不是多任务安全的！应在函数返回后拷贝到自己的缓冲区保存！
char* osGetLocalDateTimeString();


#define __DELAY_WHILE__(var, time, exp, fnow, fetm) \
	do {                                        \
		var = time;								\
		timeu_t etm, start = fnow();            \
		while(1) {                              \
			etm = fetm(start);                  \
			if(etm >= var) { var = 0; break; }  \
			if(!exp) { var = etm; break; }      \
		};                                      \
	} while(0)

/// @brief while: 当 ... 时等待 / until: 等待直到 ...
/// @param var: 变量名
/// @param time: 等待超时时间(毫秒/微秒)
/// @param express: 结束条件
/// @return: var=0 表示等待超时；var>0 表示正常，值为等待的时间
#define osDelayMsWhile(var, time, express)	__DELAY_WHILE__((var), (time),  (express), osGetMs, osElapsedMs)
#define osDelayMsUntil(var, time, express)	__DELAY_WHILE__((var), (time), !(express), osGetMs, osElapsedMs)
#define osDelayUsWhile(var, time, express)	__DELAY_WHILE__((var), (time),  (express), osGetUs, osElapsedUs)
#define osDelayUsUntil(var, time, express)	__DELAY_WHILE__((var), (time), !(express), osGetUs, osElapsedUs)


#ifdef __cplusplus
}
#endif

#endif // _SYS_CLOCK_H_
